package com.segersten.othello.service.rest;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import akka.actor.ActorRef;

import com.segersten.othello.service.akka.AkkaUtil;
import com.segersten.othello.service.akka.Auth;
import com.segersten.othello.service.akka.GameObjectPool;
import com.segersten.othello.service.akka.GameObjectReference;
import com.segersten.othello.service.akka.Player;
import com.segersten.othello.service.akka.lobby.CancelTicketAction;
import com.segersten.othello.service.akka.lobby.LobbyResponseStatus;
import com.segersten.othello.service.akka.lobby.LobbyServiceActor;
import com.segersten.othello.service.akka.lobby.LobbyState;
import com.segersten.othello.service.akka.lobby.LoginAction;
import com.segersten.othello.service.akka.lobby.MatchOpponentsAction;
import com.segersten.othello.service.akka.lobby.PlayerScore;
import com.segersten.othello.service.akka.lobby.PlayerScoreAction;
import com.segersten.othello.service.akka.lobby.RegisterAction;
import com.segersten.othello.service.akka.lobby.StateAction;
import com.segersten.othello.service.akka.lobby.StateResponse;

@Path("/lobby")
public class LobbyService {
    
    GameObjectPool gameObjectPool = new AkkaUtil();

	@GET
	@Produces({ "text/html" })
	public String start() {
		return "lobby";
	}
	
	@POST
	@Path("/login")
	@Produces({ MediaType.APPLICATION_XML })
	public Auth login(LoginRequest req) {
	    // TODO move to an actor
	    if (AuthenticateService.INSTANCE.isOK(req.getAuth()) == false) {
            throw new WebApplicationException(403);
        }
	    
	    Auth result = AuthenticateService.INSTANCE.generateToken(req.getAuth().getDomain(), req.getNickname());
	    gameObjectPool.tell(getLobbyActor(), new LoginAction(new Player(req.getNickname(), result)));
	    return result;
	}
	
	@POST
	@Path("/register")
	@Produces({ MediaType.TEXT_PLAIN })
	public String register(RegisterRequest req) {
		
	    LobbyResponseStatus response = (LobbyResponseStatus) gameObjectPool.ask(getLobbyActor(), new RegisterAction(req.getPlayer())); 
		if (response==null) {
			throw new WebApplicationException(503);
		}
		if (response.equals(LobbyResponseStatus.NonAuth)) {
            throw new WebApplicationException(403);
        }
		gameObjectPool.tell(getLobbyActor(), new MatchOpponentsAction());
		return "OK";
	}

	@POST
	@Path("/cancel")
	@Produces({ MediaType.TEXT_PLAIN })
	public String cancel(Auth auth) {		
	    LobbyResponseStatus response = (LobbyResponseStatus) gameObjectPool.ask(getLobbyActor(),new CancelTicketAction(auth));
		if (response.equals(LobbyResponseStatus.NonAuth)) {
            throw new WebApplicationException(403);
        }
		return "OK";
	}

	@POST
	@Path("/list")
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public LobbyStateResponse getState(Auth auth) {
		
	    StateResponse state = (StateResponse) gameObjectPool.ask(getLobbyActor(), new StateAction(auth));
		if (state.getStatus().equals(LobbyResponseStatus.NonAuth)) {
			throw new WebApplicationException(403);
		}
		if (state.getStatus().equals(LobbyResponseStatus.NotFound)) {
            throw new WebApplicationException(404);
        }
		System.out.println("getState1 " + state);
		LobbyStateResponse response = LobbyStateResponse.from(state.getLobbyState());
        System.out.println("getState2 " + response);
		return response;
	}

	@GET
	@Path("/historic")
	public Response getHistoric(String request) {
		throw new UnsupportedOperationException("Not implemented yet!");
	}
	
	@GET
	@Path("/score/{nickname}")
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public PlayerScore getScore(@PathParam(value = "nickname") String nickname) {
		PlayerScore state = (PlayerScore) gameObjectPool.ask(getLobbyActor(), new PlayerScoreAction(nickname));
		if (state==null) {
			throw new WebApplicationException(404);
		}
		return state;
	}

	private GameObjectReference getLobbyActor() {
		return gameObjectPool.actorFor(LobbyServiceActor.SERVICE_NAME);

	}

}
